<style>
	.CLASS .ui-search-used .listing-caption { display: none; }
	.CLASS .ui-search-used .endsection { display: none; }
	.CLASS .endsection { margin-bottom: 15px; }
	.CLASS .ui-search-used .lastclear { margin-bottom: 20px; }
	.CLASS .badge-community { background-color: #62AECA; }
	.ui-dark .CLASS .badge-community { background-color: #567e84; }
</style>

<ui-component name="box" path="common.form" config="if:~PATH~;icon:ti ti-flow green;title:@(Download components);autofocus:true;reload:?/reload;scrollbar:0;width:1200" class="hidden CLASS" plugin="CLASS">
	<nav>
		<button class="exec" data-exec="?/update" is="is-button" path="?.newupdates" config="enable"><i class="ti ti-sync"></i>@(Update all)</button>
	</nav>
	<div>
		<div class="search">
			<ui-component name="searchinput" path="?.search" config="placeholder:@(Search components)"></ui-component>
		</div>
		<ui-component name="viewbox" path="common.form" config="parent:auto;margin:30;scrollbar:1;scrollbarshadow:1">
			<div class="padding">
				<div style="margin:0 0 15px 8px">
					<div class="pull-right">
						<span class="link fs12 exec" data-exec="flow/create"><i class="ti ti-plus-circle green mr5"></i>@(Create component)</span>
					</div>
					<div class="pull-left">
						<ui-component name="input" path="?.approve" config="type:checkbox" default="true">@(Warn about component installation)</ui-component>
					</div>
					<div class="clearfix"></div>
					<hr />

					<div class="fs12">
						<span class="exec" data-exec="?/kind" data-id="action"><i class="ti ti-circle-alt legend-action mr5"></i>@(Actions)</span> &nbsp; <span class="exec" data-exec="?/kind" data-id="trigger"><i class="ti ti-circle-alt legend-trigger mr5"></i>@(Triggers)</span> &nbsp; <span class="exec" data-exec="?/kind" data-id="output"><i class="ti ti-circle-alt legend-output mr5"></i>@(Outputs)</span>
					</div>
				</div>
				<ui-component name="search" path="?.search" config="selector:figure;datasource:?.items">
					<ui-bind path="?.items" config="template" id="flowstreamcomponents" class="flowstreamcomponents block">
						<script type="text/html">
							{{ foreach n in value }}
								{{ if n.name && n.name !== '0' }}
								<div class="listing-caption" data-search="">{{ n.name }}</div>
								{{ fi }}
								{{ foreach m in n.items }}
								<figure data-search="{{ m.name }} {{ m.author }}" class="exec{{ if m.kind }} kind-{{ m.kind }}{{ fi }}{{ if m.installed }} installed{{ fi }}{{ if m.community }} community{{ fi }}" data-exec="?/install" data-id="{{ m.id }}" data-name="{{ m.name }}" data-version="{{ m.version }}" data-url="{{ m.url }}">
									<section title="{{ m.name }}">
										<div class="icon" style="background:{{ if m.color }}{{ m.color }}{{ else }}{{ m.groupcolor }}{{ fi }}"><i class="{{ m.icon | empty('fas fa-plug') }}"></i></div>
										<div class="name hellip"><span class="exec readme" data-exec="?/readme" data-prevent="true">@(Read me)</span>{{ if m.newupdate }}<span class="badge badge-green badge-small mr5 newupdate">@(update)</span>{{ fi }}{{ if m.community }}<span class="badge badge-community badge-small mr5">@(Community)</span>{{ fi }}{{ m.name }}</div>
									</section>
								</figure>
								{{ end }}
								<div class="clearfix endsection"></div>
							{{ end }}
							<div class="clearfix lastclear">&nbsp;</div>
						</script>
					</ui-bind>
				</ui-component>
				<div class="help center m nmt"><i class="ti ti-question-circle"></i>@(Official GitHub repository:) <a href="https://github.com/totaljs/flowstreamcomponents" target="_blank">https://github.com/totaljs/flowstreamcomponents</a></div>
			</div>
		</ui-component>
	</div>
	<nav>
		<button name="cancel" style="width:100%">@(Close)</button>
	</nav>
</ui-component>

<script>

	PLUGIN(function(exports) {

		var refresh = function(url, opt, callback) {
			exports.ajax('GET ' + url, function(response) {

				if (!(response instanceof Array))
					return;

				for (var item of response) {

					var com = flow.components.findItem('name', item.name);
					item.newupdate = com ? item.version.localeCompare(com.version, { numeric: true }) > 0 : false;
					item.installed = com != null;
					item.community = item.author ? !(/total\.js/i).test(item.author) : true;

					if (!item.group)
						item.group = '0';

					if (item.newupdate)
						opt.updates++;

					if (opt.groups[item.group])
						opt.groups[item.group].items.push(item);
					else
						opt.groups[item.group] = { name: item.group, color: Thelpers.color(item.group), items: [item] };

					item.groupcolor = opt.groups[item.group].color;
					item.download = '';
					opt.components.push(item);
				}

				callback();
			});
		};

		exports.reload = function() {

			var opt = {};
			opt.updates = 0;
			opt.groups = {};
			opt.components = [];

			var queue = [];

			if (common.components)
				queue.push(next => refresh(common.components, opt, next));

			if (common.components2)
				queue.push(next => refresh(common.components2, opt, next));

			queue.async(function() {

				var arr = [];
				var keys = Object.keys(opt.groups);

				keys.quicksort();

				for (var key of keys) {
					opt.groups[key].items.quicksort('name');
					arr.push(opt.groups[key]);
				}

				exports.set('newupdates', opt.updates);
				exports.set('components', opt.components);
				exports.set('items', arr);
			});
		};

		exports.check = function() {
			var components = exports.data.components;
			if (components) {
				var container = $('#flowstreamcomponents');
				var updates = 0;
				for (var item of components) {
					var com = flow.components.findItem('name', item.name);
					var is = com ? com.version !== item.version : false;
					if (item.newupdate !== is) {
						item.newupdate = is;
						container.find('figure[data-id="' + item.id + '"]').find('.newupdate').remove();
					}
					if (item.newupdate)
						updates++;
				}
				exports.set('newupdates', updates);
			}
		};

		exports.readme = function(el) {
			var id = ATTRD(el);
			var item = exports.data.components.findItem('id', id);
			FUNC.readme(item.name, item.readme);
		};

		exports.update = function() {
			var model = exports.data;
			EXEC('-approve/show', '@(Are you sure you want to apply all new updates ({0}x)?)'.format(model.newupdates), '"fas fa-sync" @(Update)', function() {
				model.components.wait(function(item, next) {
					if (item.newupdate) {

						var com = flow.components.findItem('name', item.name);
						if (com)
							$('#settings_f' + com.id).remove();

						exports.ajax('GET ' + item.url, function(response) {
							if (typeof(response) === 'string') {
								var meta = FUNC.checkhtml(response);
								if (meta) {
									var model = {};
									model.id = com ? com.id : (meta.id || '');
									model.body = response.trim();
									EXEC('-websocket/send', { TYPE: 'component_save', id: model.id || FUNC.makeid('c'), data: model.body, callback: next });
									return;
								} else
									EXEC('-notify/warning', '@(The HTML body of the component <b>"{0}"</b> is invalid)'.format(item.name.encode()));
							}
							setTimeout(next, 100);
						});

					} else
						next();
				}, function() {
					FREE();
					exports.scope();
					exports.set('mewupdates', 0);
				});
			});
		};

		exports.install = function(el) {

			var id = el.attrd2('id');
			var name = el.attrd2('name');
			var com = flow.components.findItem('name', name);

			if (com) {
				$('#settings_f' + com.id).remove();
				FREE();
			}

			var url = el.attrd2('url');
			var download = function() {
				exports.ajax('GET ' + url, function(response) {
					if (typeof(response) === 'string') {
						var meta = FUNC.checkhtml(response);
						if (meta) {
							var model = {};
							model.id = com ? com.id : (meta.id || '');
							model.body = response.trim();
							EXEC('-loading/show');
							EXEC('-websocket/send', { TYPE: 'component_save', id: model.id || FUNC.makeid('c'), data: model.body, callback: function(response) {
								EXEC('-loading/hide', 200);
								if (response.error)
									EXEC('-notify/warning', '@(The component <b>"{0}"</b> is invalid: {1})'.format(name.encode(), response.error.encode()));
								else
									el.aclass('installed');
							}});
						} else
							EXEC('-notify/warning', '@(The HTML body of the component <b>"{0}"</b> is invalid)'.format(name.encode()));
					}
				});
			};

			if (exports.data.approve)
				EXEC('-approve/show', '@(Are you sure you want to import selected component <b>"{0}"</b>?)'.format(el.attrd2('name')), '"ti ti-cloud-download" @(IMPORT)', download);
			else
				download();
		};

		exports.kind = function(el) {

			var model = exports.model;
			var id = ATTRD(el);
			var opt = {};

			opt.element = el;
			opt.items = [];
			opt.offsetY = -10;
			opt.offsetWidth = 250;

			for (var m of model.components) {
				if (m.kind === id) {
					var item = {};
					item.id = m.id;
					item.name = m.name;
					item.icon = m.icon;
					item.color = m.color;
					item.template = '<i class="{{ icon }} icon"{{ if color }} style="color:{{ color }}"{{ fi }}></i>{{ name }}';
					opt.items.push(item);
				}
			}

			opt.callback = function(sel) {
				var el = exports.element.find('figure[data-id="{0}"]'.format(sel.id));
				if (el.length)
					exports.install(el);
			};

			SETTER('directory/show', opt);
		};

		WATCH('flow.components', function() {
			setTimeout(exports.check, 100);
		});

	});

</script>